unit ORM.Types.ID;

interface

type
  TId = record
  strict private
    FValue : Double;
    FValorReferencia : string;
    function GetValue : Double;
  public
    property Value : Double read GetValue;
    function IsEmpty : Boolean;
    function ToString : string;
    function Equals(const pOther: TId): Boolean;
    procedure Clear;

    constructor Create(const pValue : Double);
    class operator Implicit(const pValue : Double) : TId;
    class operator Implicit(const pValue : TId) : Double;
    class operator Implicit(const pValue : Integer) : TId;
    class operator Implicit(const pvalue : TId) : Integer;

    class operator Add(pLeft, pRigth : TId) : TId;
    class operator Subtract(pLeft, pRigth : TId) : TId;
    class operator Multiply(pLeft, pRigth : TId) : TId;
    class operator Divide(pLeft, pRigth : TId) : TId;
    class operator IntDivide(pLeft, pRigth : TId) : TId;

    class operator Equal(pLeft, pRigth: TId) : Boolean;
    class operator GreaterThan(pLeft , pRigth : TId) : Boolean;
    class operator GreaterThanOrEqual(pLeft , pRigth : TId) : Boolean;
    class operator LessThan(pLeft , pRigth : TId) : Boolean;
    class operator LessThanOrEqual(pLeft , pRigth : TId) : Boolean;
    class operator NotEqual(pLeft , pRigth : TId) : Boolean;
  end;

implementation

uses
  System.SysUtils , ORM.Types.Base, System.Generics.Defaults;

{ TId }

class operator TId.Add(pLeft, pRigth: TId): TId;
begin
  if not pLeft.IsEmpty or not pRigth.IsEmpty then
    Result := pLeft.Value + pRigth.Value
  else
    Result.Clear;
end;

procedure TId.Clear;
begin
  FValue := 0;
  FValorReferencia := EmptyStr;
end;

constructor TId.Create(const pValue: Double);
begin
  FValue := pValue;
  FValorReferencia := CValorReferencia;
end;

class operator TId.Divide(pLeft, pRigth: TId): TId;
begin
  if not pLeft.IsEmpty or not pRigth.IsEmpty then
    Result := pLeft.Value / pRigth.Value
  else
    Result.Clear;
end;

class operator TId.Equal(pLeft, pRigth: TId): Boolean;
begin
  Result := pLeft.Equals(pRigth);
end;

function TId.Equals(const pOther: TId): Boolean;
begin
  if not IsEmpty and not pOther.IsEmpty then
    Result := TEqualityComparer<Double>.Default.Equals(Value, pOther.Value)
  else
    Result := IsEmpty = pOther.IsEmpty;
end;

function TId.GetValue: Double;
begin
  Result := FValue;
end;

class operator TId.GreaterThan(pLeft, pRigth: TId): Boolean;
begin
  Result := pLeft.Value > pRigth.Value;
end;

class operator TId.GreaterThanOrEqual(pLeft, pRigth: TId): Boolean;
begin
  Result := pLeft.Value >= pRigth.Value;
end;

class operator TId.Implicit(const pValue: Double): TId;
begin
  Result := TId.Create(pValue)
end;

class operator TId.Implicit(const pValue: TId): Double;
begin
  Result := pValue.Value;
end;

class operator TId.Implicit(const pValue: Integer): TId;
begin
  Result := TId.Create(pValue);
end;

class operator TId.Implicit(const pvalue: TId): Integer;
begin
  Result := Round(pvalue.Value)
end;

class operator TId.IntDivide(pLeft, pRigth: TId): TId;
begin
  if not pLeft.IsEmpty or not pRigth.IsEmpty then
    Result := pLeft.Value / pRigth.Value
  else
    Result.Clear;
end;

function TId.IsEmpty: Boolean;
begin
  Result := Length(FValorReferencia) = 0;
end;

class operator TId.LessThan(pLeft, pRigth: TId): Boolean;
begin
  Result := pLeft.Value < pRigth.Value;
end;

class operator TId.LessThanOrEqual(pLeft, pRigth: TId): Boolean;
begin
  Result := pLeft.Value <= pRigth.Value;
end;

class operator TId.Multiply(pLeft, pRigth: TId): TId;
begin
  if not pLeft.IsEmpty or not pLeft.IsEmpty then
    Result := pLeft.Value * pRigth.Value
  else
    Result.Clear;
end;

class operator TId.NotEqual(pLeft, pRigth: TId): Boolean;
begin
  Result := pLeft.Value <> pRigth.Value;
end;

class operator TId.Subtract(pLeft, pRigth: TId): TId;
begin
  if not pLeft.IsEmpty or not pRigth.IsEmpty then
    Result := pLeft.Value - pRigth.Value
  else
    Result.Clear;
end;

function TId.ToString: string;
begin
  Result := FloatToStr(FValue);
end;

end.
